package neuralmusic.brain.module;

import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import uk.co.drpj.util.tweaks.Tweakable;

public class Brain {

	public Vector<Tweakable> tweaks = new Vector<Tweakable>();

	public List<Connection> inputs;
	public List<Connection> outputs;
	private List<Connection> connections = new ArrayList<Connection>();
	List<Module> modules = new ArrayList<Module>();

	private Scheduler fireQueue;

	

	Random rand;

	public Brain(Random rand) {
		this.rand = rand;
	}

	public void run(Scheduler fireQueue) {

		
		for (Module m : getModules()) {
			for (Neuron n : m.getNeurons()) {
				n.setScheduler(fireQueue);
			}
		}
		
		for (Tweakable tweak : tweaks) {
			tweak.notifyObservers();
		}

		this.fireQueue = fireQueue;
		this.fireQueue.start();
		

	}

	public List<Connection> getConnections() {
		return connections;
	}

	public List<Module> getModules() {
		return modules;
	}

	public void addModule(Module module) {
		modules.add(module);

	}

	public void createConnections(float[] weights) {
		int n = weights.length;
		for (int i = 0; i < n; i++) {
			connections.add(new Connection(weights[i]));
		}
	}

	

	public List<Connection> getInputs() {
		return inputs;
	}

	public List<Connection> getOutputs() {
		return outputs;
	}

	public List<Connection> connectionFromIntArray(int[] a) {

		List<Connection> list = new ArrayList<Connection>();

		for (int ic : a) {
			list.add(connections.get(ic));
		}
		return list;
	}

	public void addConnection(Connection c) {
		connections.add(c);
	}

	public Connection getConnection(int i) {
		return connections.get(i);
	}

	public int[] toIntArray(List<Connection> inputs) {
		int list[] = new int[inputs.size()];

		for (int i = 0; i < inputs.size(); i++) {
			list[i] = getConnectionId(inputs.get(i));
		}
		return list;
	}

	public int getConnectionId(Connection connection) {
		return connections.indexOf(connection); // FIXME hashmap
	}

	public Connection createConnection(Neuron src, Neuron dst, float weight) {
		Connection c = new Connection(src, dst, weight);
		if (dst != null)
			dst.addIn(c);
		if (src != null)
			src.addOut(c);
		connections.add(c);
		return c;
	}

	public Scheduler getFireQueue() {

		return fireQueue;
	}

	public void stop() {
		this.fireQueue.stop();
	}
//	public double getCurrentTimeInSecs() {
//		return fireQueue.getCurrentTimeInSecs();
//	}

	public Module getModuleByName(String string) {
		for (Module m:modules){
			if (m.getName().equals(string)) return m;
		}
		return null;
	}

	public void setScheduler(Scheduler sched) {
		for (Module m:modules){
			m.setScheduler(sched);
		}
		
		// TODO Auto-generated method stub
		
	}

//	public void fireMe(BasicDelayed basicDelayed) {
//		fireQueue.add(basicDelayed);
//		
//	}

//	public long getDelay(TimeUnit unit, double when) {
//		return fireQueue.getDelay(unit,when);
//	}

}
